package org.zebra.mybatis.plus.core;

import cn.hutool.core.util.ReUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.*;
import org.dromara.streamquery.stream.plugin.mybatisplus.engine.mapper.IMapper;

import java.util.List;
import java.util.Map;

/**
 * mapper增强
 *
 * @param <T> 实体类型
 * @author zhanghongbin
 */
public interface MapperPlus<T> extends IMapper<T>, MPJBaseMapper<T> {

    /**--------------------------------- 查询 --------------------------------- **/

    /**
     * 返回多条结果
     *
     * @param sql sql
     * @return 列表
     */
    @SelectProvider(type = MapperPlusProvider.class, method = "sql")
    List<Map<String, Object>> selectListBySql(@Param("sql") String sql);

    /**
     * 返回单条结果
     *
     * @param sql sql
     * @return map
     */
    @SelectProvider(type = MapperPlusProvider.class, method = "sql")
    Map<String, Object> selectOneBySql(@Param("sql") String sql);

    /**
     * 返回分页
     *
     * @param page 分页对象
     * @param sql sql
     * @return 分页对象
     */
    @SelectProvider(type = MapperPlusProvider.class, method = "sql")
    Page<Map<String, Object>> selectPageBySql(IPage page, @Param("sql") String sql);

    /**
     * 参数化返回多条结果
     *
     * @param sql sql
     * @param params 参数
     * @return 列表
     */
    @SelectProvider(type = MapperPlusProvider.class, method = "sql")
    List<Map<String, Object>> selectListBySqlPlus(
            @Param("sql") String sql, @Param("params") Map<String, Object> params);

    /**
     * 参数化返回单条结果
     *
     * @param sql sql
     * @param params 参数
     * @return map
     */
    @SelectProvider(type = MapperPlusProvider.class, method = "sql")
    Map<String, Object> selectOneBySqlPlus(@Param("sql") String sql, @Param("params") Map<String, Object> params);

    /**
     * 参数化返回分页
     *
     * @param page 分页对象
     * @param sql sql
     * @param params 参数
     * @return 分页对象
     */
    @SelectProvider(type = MapperPlusProvider.class, method = "sql")
    Page<Map<String, Object>> selectPageBySqlPlus(
            IPage page, @Param("sql") String sql, @Param("params") Map<String, Object> params);

    /**
     * 修改
     *
     * @param sql sql
     * @return 修改数量
     */
    @Update("<script>${sql}</script>")
    int updateBySql(@Param("sql") String sql);

    @Delete("<script>${sql}</script>")
    int deleteBySql(@Param("sql") String sql);

    @Insert("<script>${sql}</script>")
    int insertBySql(@Param("sql") String sql);

    /**
     * 参数化增加，删除，修改
     *
     * @param sql sql
     * @param params 参数
     * @return 修改数量
     */
    @UpdateProvider(type = MapperPlusProvider.class, method = "sql")
    int updateBySqlPlus(@Param("sql") String sql, @Param("params") Map<String, Object> params);

    @DeleteProvider(type = MapperPlusProvider.class, method = "sql")
    int deleteBySqlPlus(@Param("sql") String sql, @Param("params") Map<String, Object> params);

    @InsertProvider(type = MapperPlusProvider.class, method = "sql")
    int insertBySqlPlus(@Param("sql") String sql, @Param("params") Map<String, Object> params);

    class MapperPlusProvider {

        public String sql(String sql) {
            return "<script>" + cn.hutool.core.util.XmlUtil.escape(sql) + "</script>";
        }

        public String sqlPlaceholder(String sql) {
            return "<script>" + ReUtil.replaceAll(sql, "#\\{", "#{params.") + "</script>";
        }
    }
}
